package cn.com.xy.sms.sdk.number;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.json.JSONObject;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.util.Pair;
import cn.com.xy.sms.sdk.constant.Constant;
import cn.com.xy.sms.sdk.db.ContactsDBManager;
import cn.com.xy.sms.sdk.db.entity.NumberInfo;
import cn.com.xy.sms.sdk.db.entity.NumberInfoManager;
import cn.com.xy.sms.sdk.db.entity.SysParamEntityManager;
import cn.com.xy.sms.sdk.dex.DexUtil;
import cn.com.xy.sms.sdk.log.LogManager;
import cn.com.xy.sms.sdk.util.FileUtils;
import cn.com.xy.sms.sdk.util.PriorityUtils;
import cn.com.xy.sms.sdk.util.StringUtils;
import cn.com.xy.sms.sdk.util.ThreadPoolManager;
import cn.com.xy.sms.util.EmbedNumberUtils;
import cn.com.xy.sms.util.UUIDUtils;

/* SDK-428 huangzhiqiang 20160615 start */
public class InitEmbedNumber {

    private static final String EMBED_NUMBER_VERSION_FILE = "duoqu_embed_number_version.txt";
    private static final String INIT_STATUS_NEED_INIT = "0";
    private static final String INIT_STATUS_INITIALIZED = "1";
    private static final Object LOCK = new Object();
    private static boolean mIsIniting = false;
    private static boolean mIsInitFinish = false;

    public static boolean isInitFinish() {
        return mIsInitFinish;
    }

    /**
     * 初始化内嵌号码数据
     * 
     * @param context
     */
    public static void init(final Context context) {
        synchronized (LOCK) {
            if (mIsIniting) {
                return;
            }
            mIsIniting = true;
        }
        ThreadPoolManager.INIT.execute(new Runnable() {

            @Override
            public void run() {
                try {
                    if (initialized(context)) {
                        return;
                    }
					/* IMOO-9 likuangkuang 20161014 start */
					EmbedNumberUtils.init(context);
					/* IMOO-9 likuangkuang 20161014 end */
                    setInitStatus(INIT_STATUS_NEED_INIT);

					InputStream embedNumberFileInputStream = EmbedNumberUtils.unEmbedNumberZipAndReturnInputStream();
                    importEmbedNumberFileDataToDB(embedNumberFileInputStream);

                    setInitStatus(INIT_STATUS_INITIALIZED);
                } catch (Throwable e) {
                    LogManager.e(Constant.TAG, "InitEmbedNumber run error:", e);
                } finally {
                    mIsIniting = false;
                    mIsInitFinish = true;
                }
            }
        });
    }

    private static boolean initialized(Context context) {
        return SysParamEntityManager.getIntParam(context, "init_embed_number") == 1;
    }

    private static void setInitStatus(String status) {
        SysParamEntityManager.setParam("init_embed_number", status);
    }

    /*IMOO-20 zhaojiangwei 20161221 start */
    public static int getT9Flag(String[] res,int col) {
        int flag = 0;
        if (res.length >= col+1) {
            try {
                flag = Integer.parseInt(res[col]);
            }
            catch (Throwable e) {
                // TODO: handle exception
            }
        }
        return flag;
    }
    /*IMOO-20 zhaojiangwei 20161221 end */
    
    private static void importEmbedNumberFileDataToDB(InputStream embedNumberFileInputStream) throws Exception {
        SQLiteDatabase db = null;
        LineNumberReader lineReader = null;
        try {
            db = ContactsDBManager.getSQLiteDatabase();
            SQLiteStatement stateMent = db.compileStatement(getReplaceIntoSqlTemplate());
            db.beginTransaction();
			
			/*SDK-639 likuangkuang 20161012 start*/
			// 需保证在每次循环使用该Object需要remove掉已有的key，因为不同的类型key值集合不一样
			JSONObject resultContainer = new JSONObject(); // 避免new出大量JSONObject，每个号码的数据都放在这个容器中
            Map<String, String> numberTagTypeMap = DexUtil.getNumberTagTypeMap(null);
            String line = null;
            lineReader = new LineNumberReader(new InputStreamReader(embedNumberFileInputStream));
            String version = EmbedNumberUtils.getEmbedNumberVersion();
            while ((line = lineReader.readLine()) != null) {
                String[] res = line.split("\t");
                JSONObject numberData = EmbedNumberUtils.handleNumberData(resultContainer, numberTagTypeMap, res, version);
                if (numberData == null) {
                    LogManager.d(Constant.TAG, "InitEmbedNumber importEmbedNumberFileDataToDB numberData == null: ",line);
                    continue;
                }
                int t9Flag = getT9Flag(res, 6);
                stateMent.bindString(1, res[0]);
                stateMent.bindString(2, numberData.toString());
				stateMent.bindString(3, EmbedNumberUtils.getEmbedNumberVersion());
				/*IMOO-20 zhaojiangwei 20161221 start */
				stateMent.bindLong(4, t9Flag);
				/*IMOO-20 zhaojiangwei 20161221 end */
                stateMent.executeInsert();
            }
			/*SDK-639 likuangkuang 20161012 end*/
            
//            /*SDK-637 zhaojiangwei 20160929 start*/
//            //JSONObject resultContainer = new JSONObject(); // 避免new出大量JSONObject，每个号码的数据都放在这个容器中
//            String line = null;
//            lineReader = new LineNumberReader(new InputStreamReader(embedNumberFileInputStream));
//            while ((line = lineReader.readLine()) != null) {
//                String[] res = line.split("\t");
//                JSONObject resultContainer = new JSONObject();
//                JSONObject numberData = handleDataByUniquePriorityAndReturnNumberData(resultContainer, res);
//                if (numberData == null) {
//                    LogManager.d(Constant.TAG, "InitEmbedNumber importEmbedNumberFileDataToDB numberData == null: ",line);
//                    continue;
//                }
//                stateMent.bindString(1, res[0]);
//                stateMent.bindString(2, numberData.toString());
//                stateMent.bindString(3, getEmbedNumberVersion());
//                stateMent.executeInsert();
//            }
//            /*SDK-637 zhaojiangwei 20160929 end*/
            db.setTransactionSuccessful();
        } finally {
            try {
                if (db != null) {
                    db.endTransaction();
                }
            } catch (Throwable e) {
                LogManager.e(Constant.TAG, "InitEmbedNumber importEmbedNumberFileDataToDB db.endTransaction() error:", e);
            }
            ContactsDBManager.close(db);
            FileUtils.close(lineReader);
            FileUtils.close(embedNumberFileInputStream);
        }
    }

    private static String getReplaceIntoSqlTemplate() {
        return String.format("REPLACE INTO %s (%s,%s,%s,%s)VALUES(?,?,?,?)", NumberInfoManager.TABLE_NAME,
                NumberInfoManager.NUM, NumberInfoManager.RESULT, NumberInfoManager.VERSION, NumberInfoManager.FLAG_T9);
    }
	
    /**
     * 根据联盟优先级获取号码数据并返回JSONObject格式号码识别结果
     * 
     * @param resultContainer 存放号码数据的容器，避免new出大量JSONObject，每个号码的数据都放在这个容器中
     * @param res 数据源
     * @return
     */
    /*SDK-637 zhaojiangwei 20160929 start*/
    /*private static JSONObject handleDataByUniquePriorityAndReturnNumberData(JSONObject resultContainer, String res[]) {
        // 数据格式样例：
        // (号码)res[0]:076989011688
        // (号码logo)res[1]:f88e0ee7a9ac687544b8074aa2d979e4.png
        // (联盟数据1，其中第一个字符1为数据源编码，第二个字符0代表信息是非认证信息，其余字符为号码识别名称)res[2]:10群光电子（东莞）有限公司
        // (联盟数据2，其中第一个字符2为数据源编码，第二个字符1代表信息是认证信息，其余字符为号码识别名称)res[3]:21群光电子(东莞)有限公司
        // (联盟数据3，其中第一个字符3为数据源编码，第二个字符0代表信息是非认证信息，其余字符为号码识别名称)res[4]:30群光电子有限公司
        if (res == null || res.length < 4) {
            return null;
        }
        try {
            String src = null;
            String auth = null;
            String name = null;
            boolean findSrc = false;
            int numType = 0;
            //boolean onlyOneSrc = (res.length == 3); // res.length == 3，说明只有一家数据；无须按优先级序列
            boolean onlyOneSrc = (res.length == 5); // res.length == 5，说明只有一家数据；无须按优先级序列
            //int unionDataStartIndex = 2;// 从2位开始才是多家的号码名称数据。
            int unionDataStartIndex = 4;// 从2位开始才是多家的号码名称数据。
            String uniquePriority = getUniquePriority();
            int srcSortLen = uniquePriority.length();
            for (int j = 0; j < srcSortLen; j++) {
                for (int i = unionDataStartIndex; i < res.length; i++) {
                    if (res[i].length() == 0) {
                        continue;
                    }
                    src = res[i].substring(0, 1);
                    auth = res[i].substring(1, 2);
                    name = res[i].substring(2);
                    // onlyOneSrc 说明数据只有一个来源，无须按优先级序列
                    if (onlyOneSrc || src.equals(uniquePriority.substring(j, j + 1))) {
                        findSrc = true;
                        break;
                    }
                }
                if (findSrc) {
                    break;
                }
            }
            if (StringUtils.isNull(src)) {
                LogManager
                        .e(Constant.TAG, "InitEmbedNumber handleDataByUniquePriorityAndReturnNumberData src : " + src);
            }
            String num = res[0];
            //String logo = res[1];
            String type = res[1];
            String amount = res[2];
            String logo = res[3];
            
            resultContainer.put(NumberInfo.NUM_KEY, num);
            resultContainer.put(NumberInfo.SOURCE_KEY, src);
            resultContainer.put(NumberInfo.LOGO_KEY, StringUtils.isNull(logo) ? "" : logo);
            resultContainer.put(NumberInfo.NAME_KEY, name);
            resultContainer.put(NumberInfo.NUM_TYPE_KEY, 1); // 1代表为企业号码
            resultContainer.put(NumberInfo.AUTH_KEY, "1".equals(auth) ? 1 : 0); // auth为1代表是认证数据，为0代表非认证数据
            
            resultContainer.put(NumberInfo.KEY_AMOUNT, amount);
            
            resultContainer.put(NumberInfo.VERSION_KEY, getEmbedNumberVersion());
            return resultContainer;
        } catch (Throwable e) {
            LogManager.e(Constant.TAG,
                    "InitEmbedNumber handleDataByUniquePriorityAndReturnNumberData error:", e);
        }
        return null;
    }*/
    /*SDK-637 zhaojiangwei 20160929 end*/
    
    private static JSONObject handleDataByUniquePriorityAndReturnNumberData(JSONObject resultContainer, String res[]) {
        // 数据格式样例：
        // (号码)res[0]:076989011688
        // (号码logo)res[1]:f88e0ee7a9ac687544b8074aa2d979e4.png
        // (联盟数据1，其中第一个字符1为数据源编码，第二个字符0代表信息是非认证信息，其余字符为号码识别名称)res[2]:10群光电子（东莞）有限公司
        // (联盟数据2，其中第一个字符2为数据源编码，第二个字符1代表信息是认证信息，其余字符为号码识别名称)res[3]:21群光电子(东莞)有限公司
        // (联盟数据3，其中第一个字符3为数据源编码，第二个字符0代表信息是非认证信息，其余字符为号码识别名称)res[4]:30群光电子有限公司
        if (res == null || res.length < 4) {
            return null;
        }
        try {
            String src = null;
            String auth = null;
            String name = null;
            boolean findSrc = false;
            String logo = null;
            String num = res[0];
            String numType = res[1];
            if (numType.equals("1")) {
                logo = res[2];
                
                boolean onlyOneSrc = (res.length == 4); // res.length == // 4，说明只有一家数据；无须按优先级序列
                int unionDataStartIndex = 3;// 从3位开始才是多家的号码名称数据。
                String uniquePriority = getUniquePriority();
                int srcSortLen = uniquePriority.length();
                for (int j = 0; j < srcSortLen; j++) {
                    for (int i = unionDataStartIndex; i < res.length; i++) {
                        if (res[i].length() == 0) {
                            continue;
                        }
                        src = res[i].substring(0, 1);
                        auth = res[i].substring(1, 2);
                        name = res[i].substring(2);
                        // onlyOneSrc 说明数据只有一个来源，无须按优先级序列
                        if (onlyOneSrc || src.equals(uniquePriority.substring(j, j + 1))) {
                            findSrc = true;
                            break;
                        }
                    }
                    if (findSrc) {
                        break;
                    }
                }
                if (StringUtils.isNull(src)) {
                    LogManager.e(Constant.TAG,
                            "InitEmbedNumber handleDataByUniquePriorityAndReturnNumberData src : " + src);
                }
                resultContainer.put(NumberInfo.SOURCE_KEY, src);
                resultContainer.put(NumberInfo.AUTH_KEY, "1".equals(auth) ? 1 : 0); // auth为1代表是认证数据，为0代表非认证数据
                resultContainer.put(NumberInfo.NAME_KEY, name);
                resultContainer.put(NumberInfo.LOGO_KEY, StringUtils.isNull(logo) ? "" : logo);
            }
            else{
                String tag = res[2];
                String amount = res[3];
                
                resultContainer.put(NumberInfo.KEY_TAG, tag);
                resultContainer.put(NumberInfo.KEY_AMOUNT, amount);
            }
            resultContainer.put(NumberInfo.NUM_KEY, num);
            /*SDK-637 zhaojiangwei 20160929 start*/
            resultContainer.put(NumberInfo.NUM_TYPE_KEY, numType); // 1代表为企业号码,2标记号码
            /*SDK-637 zhaojiangwei 20160929 end*/
			resultContainer.put(NumberInfo.VERSION_KEY, EmbedNumberUtils.getEmbedNumberVersion());
            return resultContainer;
        } catch (Throwable e) {
            LogManager.e(Constant.TAG,
                    "InitEmbedNumber handleDataByUniquePriorityAndReturnNumberData error:", e);
        }
        return null;
    }

    private static String mUniquePriority = null;

    private static String getUniquePriority() {
        if (mUniquePriority != null) {
            return mUniquePriority;
        }
        /*SDK-637 zhaojiangwei 20160929 start*/
        String uniquePriority = null;
        try {
            uniquePriority = defaultUniquePriority();
        /*SDK-637 zhaojiangwei 20160929 end*/
            Pair<String, Map<String, String>> pair = getChannelUnionPriorityConfigAndPriorityMap();
            String channelUnionPriorityConfig = pair.first;
            Map<String, String> priorityMap = pair.second;
            if (null != channelUnionPriorityConfig && priorityMap.size() > 0) {
                String Priority = PriorityUtils.findPriority(channelUnionPriorityConfig, UUIDUtils.getUniqueCode(),
                        priorityMap);
                if (!StringUtils.isNull(Priority)) {
                    uniquePriority = Priority;
                }
            }
        } catch (Throwable e) {
            LogManager.e(Constant.TAG, "InitEmbedNumber getUniquePriority error:", e);
        }
        mUniquePriority = uniquePriority;
        return mUniquePriority;
    }

    private static String defaultUniquePriority() {
        return ChannelType.Qihu.toString() + ChannelType.DHB.toString() + ChannelType.Sogou.toString()
                + ChannelType.ChuBao.toString();
    }

    /**
     * 获取渠道的联盟优先级配置及优先级信息map
     * 
     * @return pair.first=String类型渠道的联盟优先级配置 pair.second=Map<String,
     *         String>类型优先级信息
     */
    private static Pair<String, Map<String, String>> getChannelUnionPriorityConfigAndPriorityMap() {
        Map<String, String> priorityMap = new HashMap<String, String>();
        String channelUnionPriorityConfig = null;
        try {
            Properties properties = getUnionPriorityProperties();
            for (Map.Entry<Object, Object> entry : properties.entrySet()) {
                String key = (String) entry.getKey();
                if (key.endsWith("_union")) { // 渠道所对应的联盟配置
                    channelUnionPriorityConfig = (String) entry.getValue();
                } else {
                    priorityMap.put(key, (String) entry.getValue());
                }
            }
        } catch (Throwable e) {
            LogManager.e(Constant.TAG,
                    "InitEmbedNumber getChannelUnionPriorityConfigAndPriorityMap error:", e);
        }
        return new Pair<String, Map<String, String>>(channelUnionPriorityConfig, priorityMap);
    }

    private static Properties getUnionPriorityProperties() throws IOException {
        Properties properties = new Properties();
        properties.load(Constant.getContext().getResources().getAssets().open("unionpriority.properties"));
        return properties;
    }
}
/* SDK-428 huangzhiqiang 20160615 end */